////////////////////////////////////////////////////////////////////////////
//
//  Immense Engine Source File.
//  Copyright (C), Indloon 2012
// -------------------------------------------------------------------------
//  File name:   ieMathMatrices.h
//  Description: Random class
//  Created:     8/12/2012 Genert Org
//  Compilers:   Visual C++ 2010 Express
// -------------------------------------------------------------------------
//  History:
//
//  Extra:
// All matrices are row major. (OpenGL uses column-major matrix)
// | 0 1 |    | 0 1 2 |    |  0  1  2  3 |
// | 2 3 |    | 3 4 5 |    |  4  5  6  7 |
//            | 6 7 8 |    |  8  9 10 11 |
//                         | 12 13 14 15 |
//
////////////////////////////////////////////////////////////////////////////
#ifndef __IMMENSEENGINE_MATH_MATRICES_H
#define __IMMENSEENGINE_MATH_MATRICES_H
#pragma once


/*  1. 2x2 M A T R I X  C L A S S
	=========================================================================== */

class ieMat2 {
private:
	ieVec2 m[2];

public:
					ieMat2( void );
	explicit		ieMat2( const ieVec2 &x, const ieVec2 &y );
	explicit		ieMat2( const float xx, const float xy, const float yx, const float yy );

    const ieVec2 &	operator [] ( const int index ) const;
	ieVec2 &		operator [] ( const int index );
	ieMat2 &		operator = ( const ieMat2 &mat );
	bool			operator == ( const ieMat2 &mat ) const;
	bool			operator != ( const ieMat2 &mat ) const;
	ieMat2			operator * ( const ieMat2 &mat ) const;
	ieVec2			operator * ( const ieVec2 &vec ) const;
	ieMat2 &		operator *= ( const ieMat2 &mat );
	ieMat2 &        operator += ( const ieMat2 &mat );
	ieMat2 &        operator -= ( const ieMat2 &mat );
	ieMat2          operator + ( const ieMat2 &mat );
	ieMat2          operator - ( const ieMat2 &mat );

	/*
	void            SetRow( int index, const ieVec2 &vec);
	void            SetColumn( int index, const ieVec2 &vec );*/
	/*ieMat2 &        Get( void ) const;*/
	ieMat2 &        Identity( void );

};

/*  2. 2x2 M A T R I X  F U N C T I O N S
	=========================================================================== */
	
// -------------------------------------------------------------------------------------------------------------
ILINE ieMat2::ieMat2( void )
{
	// ...
}
// -------------------------------------------------------------------------------------------------------------
ILINE ieMat2::ieMat2( const ieVec2 &x, const ieVec2 &y )
{
	m[0] = x;
	m[1] = y;
}
// -------------------------------------------------------------------------------------------------------------
ILINE ieMat2::ieMat2( const float xx, const float xy, const float yx, const float yy )
{
    m[0][0] = xx;
    m[0][1] = xy;
    m[1][0] = yx;
    m[1][1] = yy;
}
// -------------------------------------------------------------------------------------------------------------
ILINE const ieVec2 &ieMat2::operator [] ( const int index ) const
{
	return m[index];
}
// -------------------------------------------------------------------------------------------------------------
ILINE ieVec2 &ieMat2::operator [] ( const int index )
{
	return m[index];
}
// -------------------------------------------------------------------------------------------------------------
ILINE ieMat2 &ieMat2::operator = ( const ieMat2 &mat )
{
	m[0] = mat[0];
	m[1] = mat[1];

	return *this;
}
// -------------------------------------------------------------------------------------------------------------
ILINE bool ieMat2::operator == ( const ieMat2 &mat ) const
{
	if( m[0] == mat[0] && m[1] == mat[1] )
	{
		return true;
	}
	else
	{
		return false;
	}
}
// -------------------------------------------------------------------------------------------------------------
ILINE bool ieMat2::operator != ( const ieMat2 &mat ) const
{
	if( m[0] != mat[0] && m[1] != mat[1] )
	{
		return true;
	}
	else
	{
		return false;
	}
}
// -------------------------------------------------------------------------------------------------------------
ILINE ieMat2 ieMat2::operator * ( const ieMat2 &mat ) const
{
	return ieMat2( m[0][0]*mat[0][0] + m[0][1]*mat[1][0],
                   m[0][0]*mat[0][1] + m[0][1]*mat[1][1],
				   m[1][0]*mat[0][0] + m[1][1]*mat[1][0],
				   m[1][0]*mat[0][1] + m[1][1]*mat[1][1] );
}
// -------------------------------------------------------------------------------------------------------------
ILINE ieVec2 ieMat2::operator * ( const ieVec2 &vec ) const
{
    return ieVec2( m[0][0]*vec.x + m[0][1]*vec.y,
	               m[1][0]*vec.x + m[1][1]*vec.y );
}
// -------------------------------------------------------------------------------------------------------------
ILINE ieMat2 &ieMat2::operator *= ( const ieMat2 &mat )
{
	*this = *this * mat;

	return *this;
}
// -------------------------------------------------------------------------------------------------------------
ILINE ieMat2 &ieMat2::operator += ( const ieMat2 &mat )
{
    m[0][0] += mat[0][0];
    m[0][1] += mat[0][1];
    m[1][0] += mat[1][0];
    m[1][1] += mat[1][1];

    return *this;
}
// -------------------------------------------------------------------------------------------------------------
ILINE ieMat2 &ieMat2::operator -= ( const ieMat2 &mat )
{
    m[0][0] -= mat[0][0];
    m[0][1] -= mat[0][1];
    m[1][0] -= mat[1][0];
    m[1][1] -= mat[1][1];

    return *this;
}
// -------------------------------------------------------------------------------------------------------------
ILINE ieMat2 ieMat2::operator + ( const ieMat2 &mat )
{
    return ieMat2( m[0][0] + mat[0][0],
    	           m[0][1] + mat[0][1],
    	           m[1][0] + mat[1][0],
    	           m[1][1] + mat[1][1] );
}
// -------------------------------------------------------------------------------------------------------------
ILINE ieMat2 ieMat2::operator - ( const ieMat2 &mat )
{
    return ieMat2( m[0][0] - mat[0][0],
    	           m[0][1] - mat[0][1],
    	           m[1][0] - mat[1][0],
    	           m[1][1] - mat[1][1] );
}
// -------------------------------------------------------------------------------------------------------------
/*ILINE void ieMat2::SetRow( int index, const ieVec2 &vec )
{
    m[index*2] = vec[0];
    m[index*2+1] = vec[1];
}
// -------------------------------------------------------------------------------------------------------------
ILINE void ieMat2::SetColumn( int index, const ieVec2 &vec )
{
	m[index] = vec.x;
	m[index+2] = vec.y;
}*/
// -------------------------------------------------------------------------------------------------------------
/*ILINE ieMat2 &ieMat2::Get( void ) const
{
	return ieMat2( m[0][0], m[0][1], m[1][0], m[1][1] );
}*/
// -------------------------------------------------------------------------------------------------------------
ILINE ieMat2 &ieMat2::Identity( void )
{
	m[0][0] = 1.0f;
	m[1][0] = 1.0f;
	m[0][1] = 0.0f;
	m[1][1] = 0.0f;

	return *this;
}
// -------------------------------------------------------------------------------------------------------------


#endif // __IMMENSEENGINE_MATH_MATRICES_H